using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Reflection;
using Ooganizer.API;
using Ooganizer.Server;
using Ooganizer.Client.UI.WorkspaceSelectorLib;
using Ooganizer.Platform;

namespace Ooganizer.Client.UI
{
    [Guid("AE07101B-46D4-4a98-AF68-0333EA26E113")]
    [BandObject("Ooganizer", BandObjectStyle.Horizontal | BandObjectStyle.TaskbarToolBar, HelpText = "Tame the Chaos : Ooganizer")]
    public class DeskBand : BandObjectBase
    {
        private Button btnLaunch;
        private IContainer components;
        private System.Threading.TimerCallback _clickTimerCallback;
        private System.Threading.Timer _clickTimer;
        private int _previousClick = 0;
        private ContextMenuStrip contextMenuStrip;
        private ToolStripMenuItem settingsToolStripMenuItem;
        private ToolStripMenuItem aboutToolStripMenuItem;
        private ToolStripMenuItem helpToolStripMenuItem;
        private ToolStripMenuItem hideToolStripMenuItem;
        private ToolStripMenuItem unloadToolStripMenuItem;
        private ToolStripMenuItem showToolStripMenuItem;
        private ToolStripSeparator toolStripWorkspaceOptionSeparator;
        private MouseButtons _previousClickMouseButton = MouseButtons.None;

        public DeskBand()
        {
            InitializeComponent();
            InitializeClickTimer();

            AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(OnAssemblyResolve);
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (components != null)
                    components.Dispose();
            }
            base.Dispose(disposing);
        }

        private void InitializeClickTimer()
        {
            _clickTimerCallback = new System.Threading.TimerCallback(SingleClickCallback);
        }

        #region Component Designer generated code
        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.btnLaunch = new System.Windows.Forms.Button();
            this.contextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
            this.settingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            this.unloadToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            this.hideToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            this.showToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            this.toolStripWorkspaceOptionSeparator = new System.Windows.Forms.ToolStripSeparator();
            this.contextMenuStrip.SuspendLayout();
            this.SuspendLayout();
            // 
            // btnLaunch
            // 
            this.btnLaunch.BackColor = System.Drawing.SystemColors.ControlText;
            this.btnLaunch.ContextMenuStrip = this.contextMenuStrip;
            this.btnLaunch.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.btnLaunch.Font = new System.Drawing.Font("Forte", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.btnLaunch.ForeColor = System.Drawing.SystemColors.ControlText;
            this.btnLaunch.Location = new System.Drawing.Point(0, 0);
            this.btnLaunch.Margin = new System.Windows.Forms.Padding(0);
            this.btnLaunch.Name = "btnLaunch";
            this.btnLaunch.Size = new System.Drawing.Size(24, 24);
            this.btnLaunch.TabIndex = 0;
            this.btnLaunch.TabStop = false;
            this.btnLaunch.Text = "O";
            this.btnLaunch.UseVisualStyleBackColor = false;
            this.btnLaunch.HandleCreated += new System.EventHandler(this.btnLaunch_HandleCreated);
            this.btnLaunch.HandleDestroyed += new System.EventHandler(this.btnLaunch_HandleDestroyed);
            this.btnLaunch.Click += new System.EventHandler(this.btnLaunch_Click);
            this.btnLaunch.MouseClick += new System.Windows.Forms.MouseEventHandler(this.btnLaunch_MouseClick);
            this.btnLaunch.MouseDown += new System.Windows.Forms.MouseEventHandler(this.btnLaunch_MouseDown);
            this.btnLaunch.MouseUp += new System.Windows.Forms.MouseEventHandler(this.btnLaunch_MouseUp);
            // 
            // contextMenuStrip
            // 
            this.contextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.hideToolStripMenuItem,
            this.unloadToolStripMenuItem,
            this.showToolStripMenuItem,
            this.toolStripWorkspaceOptionSeparator,
            this.settingsToolStripMenuItem,
            this.helpToolStripMenuItem,
            this.aboutToolStripMenuItem});
            this.contextMenuStrip.Name = "contextMenuStrip";
            this.contextMenuStrip.Size = new System.Drawing.Size(153, 164);
            this.contextMenuStrip.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip_Opening);
            // 
            // settingsToolStripMenuItem
            // 
            this.settingsToolStripMenuItem.Name = "settingsToolStripMenuItem";
            this.settingsToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
            this.settingsToolStripMenuItem.Text = "Settings";
            this.settingsToolStripMenuItem.Click += new System.EventHandler(this.settingsToolStripMenuItem_Click);
            // 
            // aboutToolStripMenuItem
            // 
            this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem";
            this.aboutToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
            this.aboutToolStripMenuItem.Text = "About";
            this.aboutToolStripMenuItem.Click += new System.EventHandler(this.aboutToolStripMenuItem_Click);
            // 
            // helpToolStripMenuItem
            // 
            this.helpToolStripMenuItem.Name = "helpToolStripMenuItem";
            this.helpToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
            this.helpToolStripMenuItem.Text = "Help";
            // 
            // unloadToolStripMenuItem
            // 
            this.unloadToolStripMenuItem.Name = "unloadToolStripMenuItem";
            this.unloadToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
            this.unloadToolStripMenuItem.Text = "Unload";
            this.unloadToolStripMenuItem.Click += new System.EventHandler(this.unloadToolStripMenuItem_Click);
            // 
            // hideToolStripMenuItem
            // 
            this.hideToolStripMenuItem.Name = "hideToolStripMenuItem";
            this.hideToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
            this.hideToolStripMenuItem.Text = "Hide";
            this.hideToolStripMenuItem.Click += new System.EventHandler(this.hideToolStripMenuItem_Click);
            // 
            // showToolStripMenuItem
            // 
            this.showToolStripMenuItem.Name = "showToolStripMenuItem";
            this.showToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
            this.showToolStripMenuItem.Text = "Show";
            this.showToolStripMenuItem.Click += new System.EventHandler(this.showToolStripMenuItem_Click);
            // 
            // toolStripWorkspaceOptionSeparator
            // 
            this.toolStripWorkspaceOptionSeparator.Name = "toolStripWorkspaceOptionSeparator";
            this.toolStripWorkspaceOptionSeparator.Size = new System.Drawing.Size(149, 6);
            // 
            // DeskBand
            // 
            this.BackColor = System.Drawing.SystemColors.ControlText;
            this.Controls.Add(this.btnLaunch);
            this.ForeColor = System.Drawing.SystemColors.ControlText;
            this.MaxSize = new System.Drawing.Size(24, 24);
            this.MinSize = new System.Drawing.Size(24, 24);
            this.Name = "DeskBand";
            this.Title = "";
            this.contextMenuStrip.ResumeLayout(false);
            this.ResumeLayout(false);

        }
        #endregion

        #region Other Handlers

        private void btnLaunch_HandleCreated(object sender, EventArgs e)
        {
            //MessageBox.Show("btnLaunch_Created is called!");
        }

        private void btnLaunch_HandleDestroyed(object sender, EventArgs e)
        {
            //MessageBox.Show("btnLaunch_Destroyed is called!");
        }

        #endregion

        #region Button Click Handlers

        private void btnLaunch_MouseClick(object sender, MouseEventArgs e)
        {

        }

        private void SingleClickCallback(Object arg)
        {
            switch (((MouseEventArgs)arg).Button)
            {
                case MouseButtons.Left:
                    {
                        LaunchArtifactWall();

                        break;
                    }
                case MouseButtons.Right:
                    {
                        LaunchContextMenu((MouseEventArgs)arg);

                        break;
                    }
                case MouseButtons.Middle:
                    {
                        // TODO - Handle middle button ... if desired

                        break;
                    }
                default:
                    {
                        break;
                    }
            }
        }

        private void DoubleClickCallback(MouseEventArgs args)
        {
            switch (args.Button)
            {
                case MouseButtons.Left:
                    {
                        LaunchWorkspaceSelector();

                        break;
                    }
                case MouseButtons.Right:
                    {
                        // TODO - Handle right button double click ... if desired

                        break;
                    }
                case MouseButtons.Middle:
                    {
                        // TODO - Handle middle button double click ... if desired

                        break;
                    }
                default:
                    {
                        break;
                    }
            }
        }

        private void LaunchContextMenu(MouseEventArgs args)
        {
            contextMenuStrip.Show(PointToScreen(args.Location));            
        }

        private void LaunchWorkspaceSelector()
        {
            WPFHostForm wpfHost = new WPFHostForm();

            wpfHost.ShowDialog();
        }

        private void LaunchArtifactWall()
        {
            string currentWorkspace = null;

            using (OoganizerState oogyState = new OoganizerState())
            {
                currentWorkspace = oogyState.GetCurrentWorkspace();
            }

            if (currentWorkspace != null)
            {
                LaunchWall.SpawnWallThread(currentWorkspace);
            }
        }

        private void btnLaunch_Click(object sender, EventArgs e)
        {

        }

        private void btnLaunch_MouseDown(object sender, MouseEventArgs e)
        {
            // Do not remove this handler ... it seems to quiet down the taskbar context menu 
            // so we can do our own context menu
        }

        private void btnLaunch_MouseUp(object sender, MouseEventArgs e)
        {
            int now = System.Environment.TickCount;

            if ((now - _previousClick) <= SystemInformation.DoubleClickTime &&
                e.Button == _previousClickMouseButton)
            {
                // Cancel click timer ... we've got a double click instead
                _clickTimer.Change(System.Threading.Timeout.Infinite,
                                   System.Threading.Timeout.Infinite);

                DoubleClickCallback(e);

                _previousClick = 0;
            }
            else
            {
                _previousClick = now;
                _previousClickMouseButton = e.Button;

                // Fire the OnClick event after the DoubleClickTime so that double-click handling gets a chance
                _clickTimer = new System.Threading.Timer(_clickTimerCallback,
                                                         (Object)e,
                                                         (int)(SystemInformation.DoubleClickTime * 1.3),
                                                         System.Threading.Timeout.Infinite);
            }
        }

        #endregion

        #region ContextMenu Handlers

        private void contextMenuStrip_Opening(object sender, CancelEventArgs e)
        {
            string currentWorkspace = null;
            OoganizerState.WorkspaceState workspaceState = OoganizerState.WorkspaceState.Unloaded;

            using (OoganizerState oogyState = new OoganizerState())
            {
                currentWorkspace = oogyState.GetCurrentWorkspace();

                if (currentWorkspace != null)
                {
                    workspaceState = oogyState.GetWorkspaceState(currentWorkspace);
                }
            }

            if (currentWorkspace == null)
            {
                // Hide these options when there is no workspace loaded
                this.hideToolStripMenuItem.Visible = false;
                this.unloadToolStripMenuItem.Visible = false;
                this.showToolStripMenuItem.Visible = false;
                this.toolStripWorkspaceOptionSeparator.Visible = false;
            }
            else
            {
                switch (workspaceState)
                {
                    case OoganizerState.WorkspaceState.Hidden:
                        this.hideToolStripMenuItem.Visible = false;
                        this.unloadToolStripMenuItem.Visible = true;
                        this.showToolStripMenuItem.Visible = true;
                        this.toolStripWorkspaceOptionSeparator.Visible = true;

                        break;

                    case OoganizerState.WorkspaceState.Shown:
                        this.hideToolStripMenuItem.Visible = true;
                        this.unloadToolStripMenuItem.Visible = true;
                        this.showToolStripMenuItem.Visible = false;
                        this.toolStripWorkspaceOptionSeparator.Visible = true;

                        break;

                    default:
                        // Otherwise hide workspace options
                        this.hideToolStripMenuItem.Visible = false;
                        this.unloadToolStripMenuItem.Visible = false;
                        this.showToolStripMenuItem.Visible = false;
                        this.toolStripWorkspaceOptionSeparator.Visible = false;

                        break;
                }
            }
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Display About Form ... Form should provide :
            // * company and product version information
            // * support website / phone number
            MessageBox.Show("Ooganizer 1.0");
        }

        private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Display Settings Form ... Form should provide :
            // * Settings
            MessageBox.Show("Ooganizer Settings Form");
        }

        private void hideToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string currWorkspaceName = null;

            using (OoganizerState oogyState = new OoganizerState())
            {
                currWorkspaceName = oogyState.GetCurrentWorkspace();

                if (currWorkspaceName != null)
                {
                    using (OoganizerAPIProxy proxy = oogyState.GetAPIProxy())
                    {                    
                        Workspace currentWorkspace = proxy.API.GetWorkspace(currWorkspaceName);

                        if (currentWorkspace != null)
                        {
                            if (currentWorkspace.Hide())
                            {
                                oogyState.SetWorkspaceState(currWorkspaceName, OoganizerState.WorkspaceState.Hidden);
                            }
                            else
                            {
                                // TODO: Log something here
                            }
                        }
                    }
                }
            }
        }

        private void showToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string currWorkspaceName = null;

            using (OoganizerState oogyState = new OoganizerState())
            {
                currWorkspaceName = oogyState.GetCurrentWorkspace();

                if (currWorkspaceName != null)
                {
                    using (OoganizerAPIProxy proxy = oogyState.GetAPIProxy())
                    {
                        Workspace currentWorkspace = proxy.API.GetWorkspace(currWorkspaceName);

                        if (currentWorkspace != null)
                        {
                            if (currentWorkspace.Show())
                            {
                                oogyState.SetWorkspaceState(currWorkspaceName, OoganizerState.WorkspaceState.Shown);
                            }
                            else
                            {
                                // TODO: Log something here
                            }
                        }
                    }
                }
            }
        }

        private void unloadToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string currWorkspaceName = null;

            using (OoganizerState oogyState = new OoganizerState())
            {
                currWorkspaceName = oogyState.GetCurrentWorkspace();

                if (currWorkspaceName != null)
                {
                    using (OoganizerAPIProxy proxy = oogyState.GetAPIProxy())
                    {
                        Workspace currentWorkspace = proxy.API.GetWorkspace(currWorkspaceName);

                        if (currentWorkspace != null)
                        {
                            if (currentWorkspace.Unload())
                            {
                                oogyState.SetWorkspaceState(currWorkspaceName, OoganizerState.WorkspaceState.Unloaded);
                                oogyState.SetCurrentWorkspace(null);
                            }
                            else
                            {
                                // TODO: Log something here
                            }
                        }
                    }
                }
            }
        }

        #endregion

        static System.Reflection.Assembly OnAssemblyResolve(object sender, ResolveEventArgs args)
        {
            string[] asmName = args.Name.Split(',');

            return AssemblyResolver.Resolve(asmName[0]);
        }
    }
}
